using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.UI;
using ATK.Event;
#if UNITY_EDITOR
using UnityEditor;
#endif

/// <summary>
/// 多语言实现方法，参考 http://www.open-open.com/lib/view/open1452752105261.html
/// 翻译文件编辑器 官方网站: http://poedit.net/
/// 序列化工具 http://git.oschina.net/Hont/GunGetTextSeriHelper
/// </summary>
namespace Localize
{
    // 多语言定义顺序不要改
    public enum ELanguage
    {
        En = 0,
        CN = 1,
        TW = 2,
        Ja = 3,
        None = 5000,
    }
    [ProtoBuf.ProtoContract]
    public class LanguageInfo
    {
        [ProtoBuf.ProtoMember(1)]
        public List<string> keys;
        [ProtoBuf.ProtoMember(2)]
        public List<string> values;
        public LanguageInfo()
        {
            keys = new List<string>();
            values = new List<string>();
        }
    }

    [ExecuteInEditMode]
    public class i18n
    {
        static Dictionary<string, string> CurrentLangs { get; set; }
        static ELanguage _language = ELanguage.None;
        public static ELanguage Language
        {
            get { return _language; }
            set
            {
                if (_language != value && value != ELanguage.None)
                {
                    _language = value;
                    LoadContent();
                    refreshAllUI();
                    if (EventManager.HaveInstance())
                    {
                        EventManager.Instance.DispatchEvent(new CustomEvent(EventConst.LanguageChanged));
                    }
                }
            }
        }

        public static void Reset()
        {
            _language = ELanguage.None;
#if UNITY_EDITOR
            langContentDic.Clear();
#endif
            if (CurrentLangs != null) CurrentLangs.Clear();
        }

        public i18n()
        {
            LoadContent();
        }

        public static string[] AllLanguageNames
        {
            get
            {
                string[] allLangs = System.Enum.GetNames(typeof(ELanguage));
                return allLangs;
            }
        }

        /// <summary>
        /// Translation
        /// </summary>
        public static string _(string key)
        {
            if (CurrentLangs.ContainsKey(key))
                return CurrentLangs[key];
            return key;
        }

        /// <summary>
        /// Translation
        /// </summary>
        public static string _(string key, string fallBack)
        {
            if (CurrentLangs == null) LoadContent();
            if (string.IsNullOrEmpty(key))
                return fallBack;
            string ret;
            if (CurrentLangs.TryGetValue(key, out ret))
                return ret;//.Replace("\\r", "\r\n");
            return fallBack;
        }
#if UNITY_EDITOR
        public static string[] AllKeys
        {
            get
            {
                if (CurrentLangs == null) LoadContent();
                return CurrentLangs.Keys.ToArray();
            }
        }

        public static bool HasKey(string key)
        {
            return CurrentLangs.ContainsKey(key);
        }
        public static bool HasWord(string txt)
        {
            return CurrentLangs.ContainsValue(txt);
        }
        public static string GetWordKey(string txt)
        {
            foreach (var kv in CurrentLangs)
            {
                if (kv.Value.Equals(txt))
                    return kv.Key;
            }
            return "";
        }

#if UNITY_EDITOR
        public static Dictionary<string, string> langContentDic = new Dictionary<string, string>();
        public static void AddNewWord(string key, string word)
        {
            word = word.Replace("\n", "\\r");
            string file = "properties.txt";
            word = RN2NewLine(word);
            if (langContentDic.ContainsKey(key))
                langContentDic[key] = word;
            else
                langContentDic.Add(key, word);

            if (CurrentLangs.ContainsKey(key))
            {
                CurrentLangs[key] = word;
            }
            else
            {
                CurrentLangs.Add(key, word);
            }
            string path = R.RawResourcesRoot + "Localized/" + Language.ToString() + "/";
            string filePath = path + file;
            using (System.IO.StreamWriter f = new System.IO.StreamWriter(filePath, true))
            {
                f.WriteLine();// 直接追加文件末尾，换行 
                f.Write(key + "=" + NewLine2RN(word));
            }
            AssetDatabase.Refresh();
        }
#endif

        public static void SaveSerializedFile()
        {
            // new i18n();
            foreach (ELanguage lang in System.Enum.GetValues(typeof(ELanguage)))
            {
                if (lang == ELanguage.None) continue;
                Language = lang;
                LanguageInfo li = new LanguageInfo();
                foreach (KeyValuePair<string, string> kv in CurrentLangs)
                {
                    li.keys.Add(kv.Key);
                    li.values.Add(kv.Value);
                }
                string path = R.RawResourcesRoot + "Localized/" + lang.ToString() + R.TxtSuffix;
                if (!System.IO.Directory.Exists(R.RawResourcesRoot + "Localized/" + lang.ToString())) System.IO.Directory.CreateDirectory(R.RawResourcesRoot + "Localized/" + lang.ToString());
                if (ProtoBufUtil.SerializeToFile<LanguageInfo>(path, li))
                {
#if UNITY_EDITOR
                    AssetImporter langFileAI = AssetImporter.GetAtPath(path) as AssetImporter;
                    langFileAI.assetBundleName = "localized/" + lang.ToString();
#endif
                }
            }
            AssetDatabase.Refresh();
        }
#endif
        private static void LoadContent()
        {
#if UNITY_EDITOR
            langContentDic.Clear();
            if (Language == ELanguage.None) Language = ELanguage.CN;
            CurrentLangs = new Dictionary<string, string>();
            string file = R.RawResourcesRoot + "Localized/" + Language.ToString() + "/properties.txt";
            if (!System.IO.Directory.Exists(R.RawResourcesRoot + "Localized/" + Language.ToString())) System.IO.Directory.CreateDirectory(R.RawResourcesRoot + "Localized/" + Language.ToString());
            if (!System.IO.File.Exists(file)) System.IO.File.WriteAllText(file, "");
            string[] lines = System.IO.File.ReadAllLines(file);
            foreach (string line in lines)
            {
                string[] kv = line.Split('=');
                if (kv == null || kv.Length < 2)
                    continue;
                string key = kv[0];
                string value = "";
                if (kv.Length > 2)
                {
                    value = RN2NewLine(line.Substring(line.IndexOf("=") + 1));
                }
                else
                {
                    value = RN2NewLine(kv[1]);
                }
                if (langContentDic.ContainsKey(key))
                {
                    if (langContentDic[key] == value)
                        Debug.LogError(file + ">文件内完全重复:" + key + "=" + value);
                    else
                        Debug.LogError(file + ">文件内冲突key:" + key + "=" + value);
                }
                else
                {
                    langContentDic.Add(key, value);
                }

                if (CurrentLangs.ContainsKey(key))
                {
                    if (CurrentLangs[key] == value)
                        Debug.LogError(file + ">全局完全重复:" + key + "=" + value);
                    else
                        Debug.LogError(file + ">全局冲突key:" + key + "=" + value);
                }
                else
                {
                    CurrentLangs.Add(key, value);
                }
            }
            // 只覆盖，如果properties中没有key，则忽略（注意）
            file = R.RawResourcesRoot + "Localized/" + Language.ToString() + "/overwrite_" + getOperationName() + ".txt";
            if (System.IO.File.Exists(file))
            {
                lines = System.IO.File.ReadAllLines(file);
                foreach (string line in lines)
                {
                    string[] kv = line.Split('=');
                    if (kv == null || kv.Length < 2) continue;
                    string key = kv[0];
                    if (!langContentDic.ContainsKey(key)) continue;
                    string value = "";
                    if (kv.Length > 2)
                    {
                        value = RN2NewLine(line.Substring(line.IndexOf("=", System.StringComparison.Ordinal) + 1));
                    }
                    else
                    {
                        value = RN2NewLine(kv[1]);
                    }
                    langContentDic[key] = value;
                    CurrentLangs[key] = value;
                }
            }
#else
            CurrentLangs = ReadFromSerializedFile();
#endif
        }

        private static void refreshAllUI()
        {
            Object[] allUIs = Resources.FindObjectsOfTypeAll(typeof(UIText));
            for (int i = 0; i < allUIs.Length; i++)
            {
                (allUIs[i] as UIText).Refresh();
            }
        }

        //**********************************读取**************************************

        // 根据key获取相应的语言内容
        public static void UpdateText(GameObject textObj, string key, params string[] value)
        {
            Text label = textObj.transform.GetComponent<Text>();
            string newText = _(key, label.text);
            if (value.Length > 0)
            {
                for (int i = 0; i < value.Length; i++)
                {
                    newText = string.Format(newText, value[i]);
                }
            }
            label.text = newText;
        }
        static Dictionary<string, string> ReadFromSerializedFile()
        {
            TextAsset textAsset = ResourceManager.LoadAeB<TextAsset>("Localized/" + Language.ToString());
            LanguageInfo li = ProtoBufUtil.DeSerialize<LanguageInfo>(textAsset.bytes);
            Dictionary<string, string> dic = new Dictionary<string, string>();
            for (int i = 0; i < li.keys.Count; i++)
            {
                dic.Add(li.keys[i], li.values[i]);
            }
            return dic;
        }

        public static string RN2NewLine(string str)
        {
            if (string.IsNullOrEmpty(str))
                return str;
            return str.Replace("\\n", "\r\n").Replace("\\r", "\r\n");
        }
        public static string NewLine2RN(string str)
        {
            if (string.IsNullOrEmpty(str))
                return str;
            return str.Replace("\r\n", "\\r").Replace("\n", "\\n");
        }

        public static string Prefix
        {
            get
            {
                string prefix = "";
                if (Language == ELanguage.Ja) prefix = "ja_";
                return prefix;
            }
        }

#if UNITY_EDITOR
        private static string getOperationName()
        {
#if TKG_GAMES
            return OperationTypeEnum.TKG.ToString();
#elif SUNVY
            return OperationTypeEnum.SunVy.ToString();
#else
            return OperationTypeEnum.dev.ToString();
#endif
        }
#endif
    }
}
